using System;
using System.Collections.Generic;
using System.Text;
using tKitchen;

namespace tKitchen
{
    public class tKitchenMain
    {
        DataAccess da;

        public tKitchenMain()
        {
            da = new DataAccess();
        }


        public event EventHandler RecipeCategoryUpdated = delegate { };
        public event EventHandler RecipeCategoryAdded = delegate { };
        public event EventHandler UnitUpdated = delegate { };
        public event EventHandler UnitAdded = delegate { };
        public event EventHandler IngredientUpdated = delegate { };
        public event EventHandler IngredientAdded = delegate { };
        public event EventHandler RecipeUpdated = delegate { };
        public event EventHandler RecipeAdded = delegate { };
        public event EventHandler MealPlanAdded = delegate { };
        public event EventHandler MealPlanUpdated = delegate { };

        #region Get Object functions
        public Ingredient GetIngredient(int idIn)
        {

            IngredientPO objPO = (IngredientPO)da.GetObject(typeof(IngredientPO), idIn);
            Ingredient obj = new Ingredient(objPO);
            return obj;
        }

        public Unit GetUnit(int idIn)
        {
            UnitPO objPO = (UnitPO)da.GetObject(typeof(UnitPO), idIn);
            Unit obj = new Unit(objPO);
            return obj;
        }
        public RecipeCategory GetRecipeCategory(int idIn)
        {
            RecipeCategoryPO objPO = (RecipeCategoryPO)da.GetObject(typeof(RecipeCategoryPO), idIn);
            RecipeCategory obj = new RecipeCategory(objPO);
            return obj;
        }
        #endregion

        #region Get List functions
        public List<Recipe_Ingredient> GetShoppingList(DateTime start, DateTime end)
        {

            List<Meal> mealList = new List<Meal>();
            List<MealPlan> mealPlanList = new List<MealPlan>();
            List<Recipe> recipeList = new List<Recipe>();
            List<Recipe_Ingredient> ingredientList = new List<Recipe_Ingredient>();

            //for all meal plans between the start and end dates, inclusive
            mealPlanList = this.GetMealPlanList();
            foreach (MealPlan mealPlan in mealPlanList)
            {
                if (mealPlan.Date.CompareTo(start) >= 0 &&
                    mealPlan.Date.CompareTo(end) <= 0)
                {
                    mealList.Add(mealPlan.Meal);
                }
            }



            //for all meals
            foreach (Meal meal in mealList)
            {
                foreach (Meal_Recipe mealRecipe in meal.Recipes)
                {
                    recipeList.Add(mealRecipe.Recipe);    
                }
                
            }

            //for all recipes
            //get the list of 
            //all ingredients
            foreach (Recipe recipe in recipeList)
            {
                ingredientList.AddRange(recipe.Ingredients);
            }


            //combine applicable ingredients
            //do simple combine where 
            //ingredients with same units are combined
            //worry about conversions later

            //for each ingredient
            for (int i = 0; i < ingredientList.Count; i++)
            {
                //for each remaining ingredient
                for (int j = i+1; j < ingredientList.Count; j++)
                {
                    //if the two are the same ingredient
                    //and have the same unit
                    if ((ingredientList[i].Ingredient.IngredientId == ingredientList[j].Ingredient.IngredientId) &&
                        (ingredientList[i].Unit.UnitId == ingredientList[j].Unit.UnitId))
                    {
                        //add the second to the first, and remove the second
                        ingredientList[i].Amount += ingredientList[j].Amount;
                        ingredientList.RemoveAt(j);
                    }
                }
            }




            return ingredientList;
        }

        /// <summary>
        /// Get a list of all MealPlan objects
        /// </summary>
        /// <returns></returns>
        public List<MealPlan> GetMealPlanList()
        {
            //get MealPlanPO list
            List<MealPlanPO> listPO = da.GetMealPlanList();

            //convert to MealPlan list
            List<MealPlan> list = new List<MealPlan>();
            for (int i = 0; i < listPO.Count; i++)
            {
                list.Add(new MealPlan(listPO[i]));
            }

            return list;
        }
        public List<Unit> GetUnitList()
        {
            //get UnitPO list
            List<UnitPO> listPO = da.GetUnitList();


            //convert to Unit list
            List<Unit> list = new List<Unit>();
            for (int i = 0; i < listPO.Count; i++)
            {
                list.Add(new Unit(listPO[i]));
            }

            return list;
        }
        public List<RecipeCategory> GetRecipeCategoryList()
        {
            //get RecipeCategoryPO list
            List<RecipeCategoryPO> listPO = da.GetRecipeCategoryList();


            //convert to RecipeCategory list
            List<RecipeCategory> list = new List<RecipeCategory>();
            for (int i = 0; i < listPO.Count; i++)
            {
                list.Add(new RecipeCategory(listPO[i]));
            }

            return list;
        }
        public List<Ingredient> GetIngredientList()
        {
            //get IngredientPO list
            List<IngredientPO> listPO = da.GetIngredientList();


            //convert to Ingredient list
            List<Ingredient> list = new List<Ingredient>();
            for (int i = 0; i < listPO.Count; i++)
            {
                list.Add(new Ingredient(listPO[i]));
            }

            return list;
        }
        public List<Recipe> GetRecipeList()
        {
            //get RecipePO list
            List<RecipePO> listPO = da.GetRecipeList();


            //convert to Recipe list
            List<Recipe> list = new List<Recipe>();
            for (int i = 0; i < listPO.Count; i++)
            {
                list.Add(new Recipe(listPO[i]));
            }

            return list;
        }


        #endregion

        #region Add functions
        public void AddObject(Recipe temp)
        {
            int id = da.Save(ConvertToPO(temp));

            //set the id value that this incoming recipe gets 
            //when persisted
            temp.RecipeId = id;
            RecipeAdded(this, new EventArgs());
        }
        public void AddObject(Unit temp)
        {
            da.Save(ConvertToPO(temp));
            UnitAdded(this, new EventArgs());
        }
        public void AddObject(RecipeCategory temp)
        {
            da.Save(ConvertToPO(temp));
            RecipeCategoryAdded(this, new EventArgs());
        }
        public void AddObject(Recipe_Ingredient temp)
        {
            da.Save(ConvertToPO(temp));
        }
        public void AddObject(Ingredient temp)
        {
            da.Save(ConvertToPO(temp));
            IngredientAdded(this, new EventArgs());
        }
        #endregion

        #region Update functions

        public void UpdateObject(Recipe_Ingredient temp)
        {
            da.Update(ConvertToPO(temp));
        }

        public void UpdateObject(Unit temp)
        {
            da.Update(ConvertToPO(temp));
            UnitUpdated(this, new EventArgs());
        }
        public void UpdateObject(RecipeCategory temp)
        {
            da.Update(ConvertToPO(temp));
            RecipeCategoryUpdated(this, new EventArgs());
        }
        public void UpdateObject(Ingredient temp)
        {
            da.Update(ConvertToPO(temp));
            IngredientUpdated(this, new EventArgs());
        }
        public void UpdateObject(Recipe temp)
        {
            da.Update(ConvertToPO(temp));
            RecipeUpdated(this, new EventArgs());
        }
        #endregion

        #region Delete Functions

        public void DeleteObject(MealPlan objIn)
        {
            da.Delete(ConvertToPO(objIn));
        }
        public void DeleteObject(Recipe objIn)
        {
            da.Delete(ConvertToPO(objIn));
        }

        #endregion

        public void ResetDatabase()
        {
            da.ResetDatabase();
        }

        #region BO to PO single conversions
        private MealCommentPO ConvertToPO(MealComment temp)
        {
            MealCommentPO myTempPo = new MealCommentPO();
            myTempPo.Comment = temp.Comment;
            myTempPo.Date = temp.Date;
            myTempPo.MealCommentId = temp.MealCommentId;
            return myTempPo;
        }

        private MealPlanPO ConvertToPO(MealPlan temp)
        {
            MealPlanPO myTempPO = new MealPlanPO();
            myTempPO.Date = temp.Date;
            myTempPO.Meal = ConvertToPO(temp.Meal);
            myTempPO.MealPlanId = temp.MealPlanId;
            myTempPO.Notes = temp.Notes;

            return myTempPO;
        }

        private MealPO ConvertToPO(Meal temp)
        {
            MealPO myTempPo = new MealPO();
            if (myTempPo.Comments != null)
            {
                myTempPo.Comments = ConvertToListPO(temp.Comments);
            }
            myTempPo.MealId = temp.MealId;
            myTempPo.Name = temp.Name;
            myTempPo.Rating = temp.Rating;
            myTempPo.Recipes = ConvertToListPO(temp.Recipes);

            return myTempPo;
        }
        private Meal_RecipePO ConvertToPO(Meal_Recipe temp)
        {
            Meal_RecipePO myTempPo = new Meal_RecipePO();
            myTempPo.Meal_RecipeId = temp.Meal_RecipeId;
            myTempPo.Recipe = ConvertToPO(temp.Recipe);

            return myTempPo;
        }
        private IngredientPO ConvertToPO(Ingredient temp)
        {
            IngredientPO myTempPO = new IngredientPO();
            myTempPO.Descr = temp.Descr;
            myTempPO.Name = temp.Name;
            //myTempPO.Category = temp.Category;
            myTempPO.IngredientId = temp.IngredientId;
            return myTempPO;
        }
        private RecipeCategoryPO ConvertToPO(RecipeCategory temp)
        {
            RecipeCategoryPO myTempPO = new RecipeCategoryPO();
            myTempPO.Descr = temp.Descr;
            myTempPO.Name = temp.Name;
            myTempPO.RecipeCategoryId = temp.RecipeCategoryId;
            return myTempPO;
        }
        private Recipe_IngredientPO ConvertToPO(Recipe_Ingredient temp)
        {
            Recipe_IngredientPO myTempPO = new Recipe_IngredientPO();
            myTempPO.Amount = temp.Amount;
            myTempPO.Ingredient = ConvertToPO(temp.Ingredient);
            myTempPO.Recipe_IngredientId = temp.Recipe_IngredientId;
            if (temp.Unit != null)
            {
                myTempPO.Unit = ConvertToPO(temp.Unit);
            }
            else
            {
                myTempPO.Unit = null;
            }
            return myTempPO;
        }
        private UnitPO ConvertToPO(Unit temp)
        {
            UnitPO myTempPO = new UnitPO();
            myTempPO.Abbrev = temp.Abbrev;
            myTempPO.Descr = temp.Descr;
            myTempPO.Name = temp.Name;
            myTempPO.UnitId = temp.UnitId;
            return myTempPO;
        }
        private StepPO ConvertToPO(Step temp)
        {
            StepPO myTempPO = new StepPO();
            myTempPO.Descr = temp.Descr;
            myTempPO.StepId = temp.StepId;
            return myTempPO;
        }

        private RecipePO ConvertToPO(Recipe temp)
        {
            RecipePO myTempPO = new RecipePO();
            if (temp.Category != null)
            {
                myTempPO.Category = ConvertToPO(temp.Category);
            }
            else
            {
                myTempPO.Category = null;
            }
            //myTempPO.Comments = temp.Comments;
            myTempPO.Descr = temp.Descr;
            myTempPO.Ingredients = ConvertToListPO(temp.Ingredients);
            myTempPO.Name = temp.Name;
            myTempPO.Rating = temp.Rating;
            myTempPO.RecipeId = temp.RecipeId;


            myTempPO.Steps = ConvertToListPO(temp.Steps);


            return myTempPO;
        }
        #endregion

        #region BO to PO List conversions
        private IList<Meal_RecipePO> ConvertToListPO(IList<Meal_Recipe> list)
        {
            IList<Meal_RecipePO> listPO = new List<Meal_RecipePO>();
            for (int i = 0; i < list.Count; i++)
            {
                listPO.Add(ConvertToPO(list[i]));
            }
            return listPO;
        }
        private IList<MealCommentPO> ConvertToListPO(IList<MealComment> list)
        {
            IList<MealCommentPO> listPO = new List<MealCommentPO>();
            for (int i = 0; i < list.Count; i++)
            {
                listPO.Add(ConvertToPO(list[i]));
            }
            return listPO;
        }
        private IList<Recipe_IngredientPO> ConvertToListPO(IList<Recipe_Ingredient> list)
        {
            IList<Recipe_IngredientPO> listPO = new List<Recipe_IngredientPO>();
            for (int i = 0; i < list.Count; i++)
            {
                listPO.Add(ConvertToPO(list[i]));
            }
            return listPO;
        }
        private IList<IngredientPO> ConvertToListPO(IList<Ingredient> list)
        {
            IList<IngredientPO> listPO = new List<IngredientPO>();
            for (int i = 0; i < list.Count; i++)
            {
                listPO.Add(ConvertToPO(list[i]));
            }
            return listPO;
        }
        private IList<StepPO> ConvertToListPO(IList<Step> list)
        {
            IList<StepPO> listPO = new List<StepPO>();
            for (int i = 0; i < list.Count; i++)
            {
                listPO.Add(ConvertToPO(list[i]));
            }
            return listPO;
        }

        #endregion

        /// <summary>
        /// Checks if the recipe has an ID yet.
        /// if it does, it updates this recipe
        /// if not, it will save it and set the ID
        /// </summary>
        /// <param name="myRecipe"></param>
        public void SaveRecipe(Recipe myRecipe)
        {
            //do checks to see if the each item needs to be added, or updated
            for (int i = 0; i < myRecipe.Ingredients.Count; i++)
            {
                Recipe_Ingredient temp = myRecipe.Ingredients[i];
                if (temp.Recipe_IngredientId == -1)
                {
                    int id = da.Save(ConvertToPO(temp));
                    temp.Recipe_IngredientId = id;
                }
                else
                {
                    da.Update(ConvertToPO(temp));
                }

            }

            for (int i = 0; i < myRecipe.Steps.Count; i++)
            {
                Step temp = myRecipe.Steps[i];
                if (temp.StepId == -1)
                {
                    int id = da.Save(ConvertToPO(temp));
                    temp.StepId = id;

                }
                else
                {
                    da.Update(ConvertToPO(temp));

                }

            }

            if (myRecipe.RecipeId == -1)
            {
                int id = da.Save(ConvertToPO(myRecipe));
                myRecipe.RecipeId = id;
                RecipeAdded(this, new EventArgs());
            }
            else
            {
                da.Update(ConvertToPO(myRecipe));
                RecipeUpdated(this, new EventArgs());
            }
        }

        public void SaveObject(MealPlan myMealPlan)
        {
            if (myMealPlan.Meal.MealId == -1)
            {
                for (int i = 0; i < myMealPlan.Meal.Recipes.Count; i++)
                {
                    Meal_Recipe temp = myMealPlan.Meal.Recipes[i];
                    if (temp.Meal_RecipeId == -1)
                    {
                        int id1 = da.Save(ConvertToPO(temp));
                        temp.Meal_RecipeId = id1;
                    }
                    else
                    {
                        da.Update(ConvertToPO(temp));
                    }
                }



                int id = da.Save(ConvertToPO(myMealPlan.Meal));
                myMealPlan.Meal.MealId = id;



            }
            else
            {
                da.Update(ConvertToPO(myMealPlan.Meal));
            }



            if (myMealPlan.MealPlanId == -1)
            {
                int id = da.Save(ConvertToPO(myMealPlan));
                myMealPlan.MealPlanId = id;
                MealPlanAdded(this, new EventArgs());
            }
            else
            {
                da.Update(ConvertToPO(myMealPlan));
                MealPlanUpdated(this, new EventArgs());
            }


        }




    }
}
